//
//  PhysicsManager.m
//  CandyJump
//
//  Created by Bon Lam on 16/03/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "PhysicsManager.h"

#import "Character.h"
#import "Platform.h"

//=====================================================================================================================
@implementation PhysicsManager

static PhysicsManager *sharedManager = nil;

#pragma mark PhysicsManager - Singleton
//---------------------------------------------------------------------------------------------------------------------
- (id)init
{
	self = [super init];
	if (self == nil)
    {
        return self;
    }
	
	return self;
}

//---------------------------------------------------------------------------------------------------------------------
- (void)dealloc
{
	[super dealloc];
}

//---------------------------------------------------------------------------------------------------------------------
+ (id)allocWithZone:(NSZone *)zone
{
    return [[self sharedManager] retain];
}

//---------------------------------------------------------------------------------------------------------------------
- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

//---------------------------------------------------------------------------------------------------------------------
- (id)retain 
{
    return self;
}

//---------------------------------------------------------------------------------------------------------------------
- (NSUInteger)retainCount
{
    return NSUIntegerMax;  //denotes an object that cannot be released
}

//---------------------------------------------------------------------------------------------------------------------
- (void)release
{
    //do nothing
}

//---------------------------------------------------------------------------------------------------------------------
- (id)autorelease
{
    return self;
}

//---------------------------------------------------------------------------------------------------------------------
+ (PhysicsManager *)sharedManager
{
	if (sharedManager == nil)
    {
        sharedManager = [[super allocWithZone:NULL] init];
    }
    return sharedManager;
}


#pragma mark PhysicsManager - Collision Callbacks
//---------------------------------------------------------------------------------------------------------------------
static cpBool platformCollisionBegan(cpArbiter *arb, cpSpace *space, void *data)
{
	CP_ARBITER_GET_SHAPES(arb, a, b);
	
	//	One-way platform
	if(cpvdot(cpArbiterGetNormal(arb, 0), cpv(0, -1)) <= 0)
    {
		cpArbiterIgnore(arb);
		return cpFalse;
	}	
	
	//	Should apply force
	Platform *platform = (Platform *)b->body->data;
	Character *character = (Character *)a->body->data;
	cpBody *characterBody = [character physicsBody];
	
	if ([platform isKindOfClass:[Platform class]] == NO)
    {
		return cpFalse;
	}
	
	if ([character isKindOfClass:[Character class]] == NO)
    {
		return cpFalse;
	}
	
	cpBodyResetForces(characterBody);
	cpBodySetVel(characterBody, cpv(0, platform.elasticity));

	return cpFalse;
}

static cpBool sameModelCollisionBegan(cpArbiter *arb, cpSpace *space, void *data)
{
	// Ignore the collision of same type model
	return cpFalse;
}

//---------------------------------------------------------------------------------------------------------------------
+ (void)setupCollisionCallbacks:(cpSpace *)space;
{
	cpSpaceAddCollisionHandler(space, MODEL_COLLISION_TYPE_CHARACTER, MODEL_COLLISION_TYPE_PLATFORM, platformCollisionBegan, NULL, NULL, NULL, self);
	cpSpaceAddCollisionHandler(space, MODEL_COLLISION_TYPE_PLATFORM, MODEL_COLLISION_TYPE_PLATFORM, sameModelCollisionBegan, NULL, NULL, NULL, self);	
}

@end
